﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using caedisi.Web.DataModel;
using System.ComponentModel;
using caedisi.Controller;
using caedisi.Views.Controls;
using caedisi.Models;
using caedisi.Common;
using caedisi.Helpers;
using System.Collections.ObjectModel;
//using caedisi.Web.DataModel;

namespace caedisi.Views
{
    /// <summary>
    /// 
    /// </summary>
    public partial class CellularAutomataParameters : ChildWindow, INotifyPropertyChanged
    {
        int numberOfRulesCreated = 0;
        CellularAutomata cellular = new CellularAutomata();
        /// <summary>
        /// Initializes a new instance of the <see cref="CellularAutomataParameters"/> class.
        /// </summary>
        public CellularAutomataParameters()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CellularAutomataParameters"/> class.
        /// </summary>
        /// <param name="cellularAutomata">The cellular automata.</param>
        public CellularAutomataParameters(CellularAutomata cellularAutomata, EnumCellularAutomataParametersEditMode editMode)
        {
            this.CurrentCellularAutomata = cellularAutomata;
            cellular = this.CurrentCellularAutomata;
            this.EditMode = editMode;
            InitializeComponent();
        }


        private CellularAutomata _CurrentCellularAutomata;
        /// <summary>
        /// Gets or sets the current cellular automata.
        /// </summary>
        /// <value>
        /// The current cellular automata.
        /// </value>
        public CellularAutomata CurrentCellularAutomata
        {
            get
            {
                return _CurrentCellularAutomata;
            }
            set
            {
                if (_CurrentCellularAutomata != value)
                {
                    _CurrentCellularAutomata = value;
                    this.RaisePropertyChanged("CurrentCellularAutomata");

                }
            }
        }


        private Simulation _CurrentSimulation;
        /// <summary>
        /// Gets or sets the current simulation.
        /// </summary>
        /// <value>
        /// The current simulation.
        /// </value>
        public Simulation CurrentSimulation
        {
            get
            {
                return _CurrentSimulation;
            }
            set
            {
                if (_CurrentSimulation != value)
                {
                    _CurrentSimulation = value;
                    this.RaisePropertyChanged("CurrentSimulation");

                }
            }
        }



        private EnumCellularAutomataParametersEditMode _EditMode;
        /// <summary>
        /// Gets or sets the edit mode.
        /// </summary>
        /// <value>
        /// The edit mode.
        /// </value>
        public EnumCellularAutomataParametersEditMode EditMode
        {
            get
            {
                return _EditMode;
            }
            set
            {
                if (_EditMode != value)
                {
                    _EditMode = value;
                    this.RaisePropertyChanged("EditMode");
                    OnEditModeChanged();
                }
            }
        }

        /// <summary>
        /// Called when [edit mode changed].
        /// </summary>
        private void OnEditModeChanged()
        {
            if (this.EditMode == EnumCellularAutomataParametersEditMode.New || this.EditMode == EnumCellularAutomataParametersEditMode.Define)
                this.IsNeighbourhoodTypeEnabled = true;
            else
                this.IsNeighbourhoodTypeEnabled = false;
            this.IsThisEnabled = (this.EditMode == EnumCellularAutomataParametersEditMode.New);
            //this.IsNeighbourhoodTypeEnabled = (this.EditMode == EnumCellularAutomataParametersEditMode.Edit);
        }


        private bool _IsNeighbourhoodTypeEnabled = true;
        /// <summary>
        /// Gets or sets the is neighbourhood type enabled.
        /// </summary>
        /// <value>
        /// The is neighbourhood type enabled.
        /// </value>
        public bool IsNeighbourhoodTypeEnabled
        {
            get
            {
                return _IsNeighbourhoodTypeEnabled;
            }
            set
            {
                if (_IsNeighbourhoodTypeEnabled != value)
                {
                    _IsNeighbourhoodTypeEnabled = value;
                    this.RaisePropertyChanged("IsNeighbourhoodTypeEnabled");

                }
            }
        }


        private bool _IsThisEnabled = true;
        /// <summary>
        /// Gets or sets the is neighbourhood type enabled.
        /// </summary>
        /// <value>
        /// The is neighbourhood type enabled.
        /// </value>
        public bool IsThisEnabled
        {
            get
            {
                return _IsThisEnabled;
            }
            set
            {
                if (_IsThisEnabled != value)
                {
                    _IsThisEnabled = value;
                    this.RaisePropertyChanged("IsThisEnabled");

                }
            }
        }




        /// <summary>
        /// Handles the Click event of the OKButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonValidateAndAcceptButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.CurrentCellularAutomata.NeighbourhoodTypeId == 0)
            {
                MessageBox.Show("Please choose the neibourhood type first", "Validation Error", MessageBoxButton.OK);
                return;
            }
            if (string.IsNullOrEmpty(this.CurrentCellularAutomata.Name))
            {
                MessageBox.Show("Please choose a name", "Validation Error", MessageBoxButton.OK);
                return;
            }

            if (string.IsNullOrEmpty(this.CurrentCellularAutomata.Description))
            {
                MessageBox.Show("Please choose a description", "Validation Error", MessageBoxButton.OK);
                return;
            }

            //Test Collision
            Collection<RuleValidationError> validationResultsCollisionRules = EntityHelper.ValidateTransitionRulesCollision(this.CurrentCellularAutomata);

            //Test Inclusion
            Collection<RuleValidationError> validationResultsInclusionRules = EntityHelper.ValidateTransitionRulesInclusion(this.CurrentCellularAutomata);

            if (validationResultsCollisionRules.Count > 0 || validationResultsInclusionRules.Count > 0)
            {
                TransitionRulesValidationReport validationReportWindow = new TransitionRulesValidationReport(validationResultsCollisionRules, validationResultsInclusionRules);
                validationReportWindow.Show();
                validationReportWindow.Closed += new EventHandler((se, ev) =>
                {
                    if (validationReportWindow.DialogResult == true)
                    {
                        //if (this.EditMode == EnumCellularAutomataParametersEditMode.New)
                        //    EntityHelper.SetCellularAutomataHierarchy(this.CurrentCellularAutomata, EnumCellStateType.Contaminated);
                        this.DialogResult = true;
                    }
                });
            }
            else
            {
                //create the cellular hierarchy data
                //if (this.EditMode == EnumCellularAutomataParametersEditMode.New)
                //    EntityHelper.SetCellularAutomataHierarchy(this.CurrentCellularAutomata, EnumCellStateType.Contaminated);
                this.DialogResult = true;
            }

        }



        /// <summary>
        /// Handles the Click event of the CancelButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }



        /// <summary>
        /// Handles the Click event of the ButtonAddNewTransitionRule control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonAddNewTransitionRule_Click(object sender, RoutedEventArgs e)
        {
            if (this.CurrentCellularAutomata.NeighbourhoodTypeId == 0)
            {
                MessageBox.Show("Please choose the neibourhood type first", "Validation Error", MessageBoxButton.OK);
                return;
            }

            numberOfRulesCreated++;

            TransitionRule transitionRule = EntityHelper.GenerateGenericTransitionRule(
                "Rule #" + numberOfRulesCreated,
                string.Empty,
                comboBoxNeighbourhoodType.SelectedItem as NeighbourhoodType,
                this.CurrentCellularAutomata.RadiusVisibility);

            //by adding the transition rule to the Cellular Automata, the grid will automatically refresh with the new transition rule getting added as the grid of transition rules are "bound"
            // to the collection of transition rules 
            this.CurrentCellularAutomata.TransitionRules.Add(transitionRule);


        }

        /// <summary>
        /// Generates the generic transition rule.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="description">The description.</param>
        /// <param name="neighbourhoodType">Type of the neighbourhood.</param>
        /// <param name="radiusVisibility">The radius visibility.</param>
        /// <returns></returns>


        private void ButtonGenerateContaminationRules_Click(object sender, RoutedEventArgs e)
        {
            if (this.CurrentCellularAutomata.NeighbourhoodTypeId == 0)
            {
                MessageBox.Show("Please choose the neibourhood type first", "Validation Error", MessageBoxButton.OK);
                return;
            }

            //first clear all the existing contamination rules. starting from the end            
            for (int i = this.CurrentCellularAutomata.TransitionRules.Count - 1; i >= 0; i--)
            {
                TransitionRule existingContaminationRule = this.CurrentCellularAutomata.TransitionRules.ElementAt(i);
                CellularAutomataController.Instance.RemoveTransitionRule(existingContaminationRule, this.CurrentCellularAutomata);
            }

            EntityHelper.GenerateContaminationRule(this.CurrentCellularAutomata, comboBoxNeighbourhoodType.SelectedItem as NeighbourhoodType, ref numberOfRulesCreated);

        }



        /// <summary>
        /// Handles the Click event of the ButtonRemoveTransitionRule control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonRemoveTransitionRule_Click(object sender, RoutedEventArgs e)
        {
            Button buttonRemove = sender as Button;
            TransitionRule transitionRuleToDelete = buttonRemove.CommandParameter as TransitionRule;

            MessageBoxResult result = MessageBox.Show("Do you really want to remove the transitin rule <" + transitionRuleToDelete.Name + ">?", "Delete Rule Confirmation", MessageBoxButton.OKCancel);
            if (result == MessageBoxResult.OK)
            {
                CellularAutomataController.Instance.RemoveTransitionRule(transitionRuleToDelete, cellular);
            }
        }

        private void stackOfRules_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ;
        }


        #region INotifiedPropertyChange
        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// Raises the property changed.
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        protected virtual void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion


        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.CurrentCellularAutomata.NeighbourhoodTypeId = 3;
            
            numberOfRulesCreated = 0;
            

            GetAlgorithm algorithmWindow = new GetAlgorithm();
            algorithmWindow.Show();
            algorithmWindow.Closed += new EventHandler(
                (o, ev) =>
                {
                    if (algorithmWindow.DialogResult == true)
                    {
                        CellularAutomataController.Instance.Load(algorithmWindow.SelectedCellularAutomataId,
                            existingCellularAutomata =>
                            {
                                this.CurrentCellularAutomata.NeighbourhoodTypeId = existingCellularAutomata.NeighbourhoodTypeId;

                                try
                                {
                                    foreach (TransitionRule tr in existingCellularAutomata.TransitionRules)
                                    {
                                        numberOfRulesCreated++;
                                        TransitionRule transitionRule = tr;
                                        this.CurrentCellularAutomata.TransitionRules.Add(tr);

                                    }

                                    this.CurrentCellularAutomata.RadiusContamination = existingCellularAutomata.RadiusContamination;
                                    this.CurrentCellularAutomata.RadiusVisibility = existingCellularAutomata.RadiusVisibility;
                                    this.CurrentSimulation = new Simulation(this.CurrentCellularAutomata);
                                }
                                catch (Exception ex)
                                {
                                    MessageBox.Show(ex.ToString());
                                }

                                });

                    }
                }
                );

        }



    }
}

